<?php

namespace app\mini\controller\salesman;

use app\common\enum\account\PaymentPayeeType;
use app\common\enum\order\CheckStatus;
use app\common\enum\order\OrderChanel;
use app\common\enum\order\PayeeType;
use app\common\enum\order\PayStatus;
use app\common\enum\order\PayType;
use app\common\enum\order\ReasonType;
use app\common\enum\order\ReceiveType;
use app\common\model\AccountRecord;
use app\common\model\DealerGoods;
use app\common\model\DeliveryLog;
use app\common\model\ReceiveLog;
use app\common\model\Refund;
use app\common\service\annotation\ControllerAnnotation;
use app\common\service\annotation\NodeAnnotation;
use app\common\controller\ApiController;
use app\common\enum\order\GoodsType;
use app\common\enum\order\OrderStatus;
use app\common\enum\order\OrderType;
use app\common\exception\BaseException;
use app\common\model\DealerGoodsSpec;
use app\common\model\SalesmanDealer;
use app\common\validate\OrderValidate;
use app\company\model\AccountPaymentRecord;
use app\company\model\CompanyOrder;
use app\company\model\CompanyOrderDetail;
use app\company\model\CompanyWarehouseGoods;
use app\company\model\StoreBalanceLog;
use app\mini\model\Cart;
use app\common\model\SalesmanStore;
use app\mini\model\ChangeCompanyOrderLog;
use app\Request;
use think\App;
use think\db\exception\DbException;
use think\response\Json;

/**
 * @ControllerAnnotation (title="订单相关")
 */
class Order extends ApiController
{
    private mixed $dealer_id;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model         = new CompanyOrder();
        $this->validateClass = OrderValidate::class;
        $this->dealer_id     = (new SalesmanDealer)->where('salesman_id', $this->uid)->order('id desc')
                                                   ->value('dealer_id');
        $this->joinTable     = 'detail,store';
    }

    /**
     * @NodeAnnotation(title="结算台")
     * @return Json
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * TODO 检查一下代码是否要兼容车销
     */
    public function settle(): Json
    {
        $get = $this->request->get();
        if (empty($get['cart_id'])) {
            return $this->error('购物车参数缺失！');
        }
        if (empty($get['store_id'])) {
            return $this->error('门店参数缺失！');
        }
        // 获取购物车内商品信息
        // 获取门店应收账款金额（该次订单内购物车金额 + 以往未结算的订单金额）
        // 获取门店对应业务员的预存款金额
        $list['goods'] = (new Cart())->with([
                                                    'goods' => function ($query)
                                                    {
                                                        $query->field('id,name,code69,image');
                                                    },
                                                    'spec'  => function ($query)
                                                    {
                                                        $query->field('id,name,unit,image,stock');
                                                    }
                                            ])->where('id', 'in', $get['cart_id'])->select()->toArray();
        // 遍历购物车金额
        $cartMoney = round(array_sum(array_column($list['goods'], 'total_price')),2);
        // 获取门店未结算金额
        //        $orderMoney = $this->model->where('store_id', $get['store_id'])->where('salesman_id',$this->uid)
        //            ->where('pid',0)->where('pay_status',PayStatus::NOT_SETTLED)->sum('unsay_amount');
        $list['receive_money'] = $cartMoney;
        //        $list['balance'] = (new SalesmanStore())->where('store_id', $get['store_id'])->where('salesman_id',$this->uid)->value('balance');
        $list['is_bill'] = (new SalesmanStore())->where('store_id', $get['store_id'])->where('salesman_id', $this->uid)
                                                ->value('is_bill');
        return $this->success($list);
    }

    /**
     * @NodeAnnotation(title="小程序下单")
     */
    public function add(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        if (!$this->dealer_id) {
            return $this->error('业务员无经销商，不可下单！');
        }
        $this->sceneValidate($post, 'add');
        try {
            $this->model->transaction(function () use ($post)
            {
                $downString = '';
                // 处理订单数据
                $detail = array_map(function ($vo) use ($post, &$downString)
                {
                    // 查询商品状态
                    $info = (new DealerGoods())->field('id,name,status')->where('id', $vo['dealer_goods_id'])->find();
                    if (!$info || $info['status'] == 2) {
                        $downString .= '商品【' . $info['name'] . '】';
                    }
                    // 赠送金额为0
                    if (!$vo['true_price']) $vo['true_price'] = $vo['sale_price'];
                    if ($vo['goods_type'] == GoodsType::GIFT) $vo['true_price'] = 0;
                    $vo['total_price'] = $vo['true_price'] * $vo['num'];
                    return $vo;
                }, json_decode($post['detail'], true));
                if ($downString != '') {
                    throw new BaseException(['message' => $downString . '已禁用或不存在，请删除后再下单！']);
                }
                // 订单公共信息
                $commonOrder = [
                    'company_id'    => $this->companyId,
                    'dealer_id'     => $this->dealer_id,
                    'salesman_id'   => $this->uid,
                    'order_status'  => OrderStatus::BEING,
                    'check_status'  => CheckStatus::YES_CHECK,
                    'store_id'      => $post['store_id'],
                    'receive_type'  => $post['receive_type'],
                    'remark'        => $post['remark'],
                    'order_channel' => OrderChanel::MINI_PROGRAM,
                    'is_cx'         => $post['is_cx'],
                ];

                // 使用 array_filter 筛选出 goods_type 获取销售金额
                $xsAmountArray = array_filter($detail, function ($item)
                {
                    return in_array($item['goods_type'], [GoodsType::SALE]);
                });

                // 2024.12.02 新增判断库存
                $this->checkStock($xsAmountArray,$post);

                // 主订单信息
                $order                  = $commonOrder;
                $order['order_no']      = generateOrderNo('KD');
                $order['order_amount']  = array_sum(array_column($xsAmountArray, 'total_price'));
                $order['return_amount'] = 0;
                $order['unsay_amount']  = $order['order_amount'] + $order['return_amount'];

                // 子订单信息
                $childOrder = [];
                $info       = $commonOrder;
                // 所有类型
                $goodsType = array_column($detail, 'goods_type');

                // 销售单
                if (in_array(GoodsType::SALE, $goodsType) || in_array(GoodsType::GIFT, $goodsType)) {
                    $info['order_no']      = $order['order_no'] . '-' . OrderType::SALES;
                    $info['order_type']    = OrderType::SALES;
                    $info['order_amount']  = $order['order_amount'];
                    $info['return_amount'] = 0;
                    $info['unsay_amount']  = $order['unsay_amount'];
                    $childOrder[]          = $info;
                }

                // 保存主订单
                $save = $this->model->save($order);
                if ($save) {
                    $childOrder = array_map(function ($vo)
                    {
                        $vo['pid'] = $this->model->id;
                        return $vo;
                    }, $childOrder);
                    $this->model->saveAll($childOrder);
                }
                $driver_money = $assist_driver_money = 0;
                // 保存订单详情
                $detail = array_map(function ($vo)use(&$driver_money,&$companyOrderId,&$assist_driver_money,$post)
                {
                    $vo['company_order_pid'] = $this->model->id;
                    if ($vo['goods_type'] == GoodsType::SALE || $vo['goods_type'] == GoodsType::GIFT) {
                        // 查询销售类型主键
                        $companyOrderId = $this->model->where('pid', $this->model->id)
                                                      ->where('order_type', OrderType::SALES)->value('id');
                        if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                        // 查询库存量 TODO 兼容一下车销库存 company_warehouse_goods 表 stock为换算出的最小库存数量
                        $stockInfo = (new DealerGoodsSpec())->where('id', $vo['dealer_goods_spec_id'])
                                                            ->field('stock,freeze_stock,driver_money,ratio,assist_driver_money')->find();
                        $driver_money = bcadd($driver_money,bcmul($stockInfo['driver_money'],$vo['num'],2),2);
                        $assist_driver_money = bcadd($assist_driver_money,bcmul($stockInfo['assist_driver_money'],$vo['num'],2),2);
                        $vo['driver_money'] = bcmul($stockInfo['driver_money'],$vo['num'],2);
                        $vo['assist_driver_money'] = bcmul($stockInfo['assist_driver_money'],$vo['num'],2);
//                        $stock     = $stockInfo['stock'] - $stockInfo['freeze_stock'];
//                        if ($stockInfo['stock'] < $vo['num']) throw new BaseException(['message' => '库存不足']);
                        $vo['company_order_id'] = $companyOrderId;
                        // 增加经销商商品下单库存和销量
//                        (new DealerGoodsSpec())->where('id', $vo['dealer_goods_spec_id'])
//                                               ->dec('stock', $vo['num'])
//                                               ->inc('freeze_stock', $vo['num'])
//                                               ->inc('virtual_sales', $vo['num'])
//                                               ->inc('actual_sales', $vo['num'])->save();
                        if($post['is_cx'] == 1){
                            (new DealerGoods())->where('id', $vo['dealer_goods_id'])->dec('sales_stock', $vo['num']*$stockInfo['ratio'])->save();
                        }else{
                            (new CompanyWarehouseGoods())
                                ->where('warehouse_id',$post['warehouse_id'])
                                ->where('dealer_goods_id', $vo['dealer_goods_id'])
                                ->dec('stock', $vo['num']*$stockInfo['ratio'])->save();
                        }
                    }
                    $vo['company_warehouse_id'] = $post['warehouse_id'];
                    unset($vo['id']);
                    return $vo;
                }, $detail);
                // 回填司机配送收益
                $this->model->where('pid', $this->model->id)
                    ->where('order_type', OrderType::SALES)->save(['driver_money' => $driver_money, 'assist_driver_money' => $assist_driver_money]);
                (new CompanyOrderDetail())->saveAll($detail);

                // 删除对应购物车的内容
                (new Cart())->where('store_id', $post['store_id'])->where('company_warehouse_id',$post['warehouse_id'])->where('salesman_id', $this->uid)->whereIn('goods_type',[1,2])->delete();
                // 如果对应订单内是预存款结算，需要把预存款转入冻结金额字段
                if ($post['receive_type'] == ReceiveType::YC) {
                    $orderMoney = $order['unsay_amount'];
                    $salesmanStoreInfo = (new SalesmanStore())->where('store_id', $post['store_id'])->where('salesman_id', $this->uid)->find();
                    $oldBalance = $salesmanStoreInfo['balance'];
                    $oldFreeze = $salesmanStoreInfo['freeze'];
                    if($salesmanStoreInfo['balance'] < $orderMoney) {
                        if($post['is_cx'] == 2) throw new BaseException(['message' => '预存款不足']);
                        $orderMoney = $salesmanStoreInfo['balance'];
                    }
                    $salesmanStoreInfo->dec('balance', $orderMoney)->inc('freeze', $orderMoney)->save();
                    // 修改订单的已付预存款余额
                    $this->model->where('id',$companyOrderId)->save(['yc_money'=>$orderMoney]);
                    // 生成余额变动记录
                    $data = [
                        'company_id' => $this->companyId,
                        'salesman_id' => $this->uid,
                        'store_id' => $post['store_id'],
                        'creator_type' => StoreBalanceLog::TYPE_SALESMAN,
                        'creator_id' => $this->uid,
                        'company_order_id' => $companyOrderId,
                        'old_balance' => $oldBalance,
                        'new_balance' => bcsub($oldBalance,$orderMoney,2),
                        'old_freeze' => $oldFreeze,
                        'new_freeze' => bcadd($oldFreeze,$orderMoney,2),
                        'remark' => StoreBalanceLog::REMARK_ORDER,
                    ];
                    (new StoreBalanceLog())->save($data);
                }
                if($post['is_cx'] == 2){
                    $this->dealCx($this->model->id,$post);
                }
            });
        } catch (\Exception $e) {
            return $this->error('开单失败' . $e->getMessage(). '--' .$e->getLine());
        }
        return $this->success('开单成功');
    }

    private function checkStock($xsAmountArray,$post): void
    {
        if($post['is_cx'] == 1){
            $goodsArray = arrayGroupBy($xsAmountArray,function ($item) {
                return $item['dealer_goods_id'];
            });
            foreach ($goodsArray as $key => $goods) {
                $goodsInfo = (new DealerGoods())->where('id', $key)->find();
                $orderNum = 0;
                foreach ($goods as $spec){
                    $specInfo = (new DealerGoodsSpec())->where('id', $spec['dealer_goods_spec_id'])->find();
                    if (!$specInfo['ratio']) throw new BaseException(['message' => '请先维护【'.$goodsInfo['name'].'】换算比例']);
                    $orderNum += $spec['num'] * $specInfo['ratio'];
                }
                if ($orderNum > $goodsInfo['sales_stock']) throw new BaseException(['message' => $goodsInfo['name'].'库存不足']);
            }
        }else{
            $goodsArray = arrayGroupBy($xsAmountArray,function ($item) {
                return $item['dealer_goods_id'];
            });
            foreach ($goodsArray as $key => $goods) {
                $goodsInfo = (new CompanyWarehouseGoods())->where('dealer_goods_id', $key)
                    ->where('warehouse_id',$post['warehouse_id'])->find();
                $orderNum = 0;
                foreach ($goods as $spec){
                    $specInfo = (new DealerGoodsSpec())->where('id', $spec['dealer_goods_spec_id'])->find();
                    $orderNum += $spec['num'] * $specInfo['ratio'];
                }
                if ($orderNum > $goodsInfo['stock']) throw new BaseException(['message' => $goodsInfo['name'].'库存不足']);
            }
        }
    }

    private function dealCx($pid,$post)
    {
        $info = $this->model->where('pid', $pid)->where('order_type', OrderType::SALES)->find();
        // 处理司机签收数量和金额
        $this->dealOrder($info);
        $update = [
            'order_status' => OrderStatus::FINISH
        ];
        $newInfo = $this->model->where('pid', $pid)->where('order_type', OrderType::SALES)->find();
        if ($post['receive_type'] == ReceiveType::NOW) {
            $update = $this->dealNow($newInfo, $post, $update);
        }
        elseif ($post['receive_type'] == ReceiveType::YC) {
            $update = $this->dealYc($newInfo, $post, $update);
        }
        // 修改子订单信息
        $son = $parent = $update;
        $son['id'] = $newInfo['id'];
        $this->model->update($son);
        // 修改主订单信息
        $parent['id'] = $newInfo->pid;
        $this->model->update($parent);
    }

    private function dealOrder($info): void
    {
        // 不论什么订单状态，把司机签收的数量金额回填至订单和详情内
        $info->save(['delivery_amount' => $info->order_amount]);
        $detailModel = new CompanyOrderDetail();
        $details = $detailModel->where('company_order_id',$info->id)->select();
        foreach ($details as $goods) {
//            if ($goods['delivery_num'] > $detail['num']) throw new BaseException(['message' => '签收数量不能大于订单数量']);
            $goods->save(['delivery_num' => $goods['num'], 'delivery_total_price' => $goods['total_price']]);
        }
    }

    private function dealNow($info, $post, $update): array
    {
        // 现结，要前端返回金额，判断是否支付完，提交拍照信息
        $payStatus = PayStatus::NOT_SETTLED;
        if ($post['money'] == $info['delivery_amount']) {
            $payStatus = PayStatus::SETTLED;
        } elseif ($post['money'] < $info['delivery_amount'] && $post['money'] > 0) {
            $payStatus = PayStatus::HALF_SETTLED;
        } elseif ($post['money'] > $info['delivery_amount']) {
            throw new BaseException(['message' => '支付金额不能大于订单金额']);
        }
        $update['pay_amount']   = $post['money'];
        $update['pay_type']     = $post['pay_type'];
        $update['unsay_amount'] = $info->delivery_amount - $post['money'];
        $update['pay_status']   = $payStatus;
        // 2024.11.13 更新对账
        $accountModel = new AccountRecord();
        $accountInfo  = $accountModel->where('company_id', $this->companyId)
            ->where('payee_type', AccountRecord::SALESMAN)
            ->where('payee_id', $this->uid)->find();
        $submitMoney  = $checkMoney = 0;
        if ($post['pay_type'] == PayType::CASH) {
            $submitMoney = $post['money'];
        } else {
            $checkMoney = $post['money'];
        }
        if (!$accountInfo) {
            $accountData = [
                'company_id'   => $this->companyId,
                'payee_type'   => AccountRecord::SALESMAN,
                'payee_id'     => $this->uid,
                'total_money'  => $post['money'] ?? 0,
                'real_money'   => 0,
                'submit_money' => $submitMoney,
                'check_money'  => $checkMoney,
            ];
            $accountModel->save($accountData);
            $accountId = $accountModel->getKey();
        } else {
            $accountInfo->inc('total_money', $post['money'])->inc('submit_money', $submitMoney)
                ->inc('check_money', $checkMoney)->save();
            $accountId = $accountInfo->id;
        }
        // 生成收款单列表信息
        $this->addAccountPaymentRecord($post, $accountId, $info);
        // 组装支付交易明细信息
        $payData = [
            'company_id'        => $this->companyId,
            'store_id'          => $info->store_id,
            'payee_type'        => PayeeType::SALESMAN,
            'payee_id'          => $this->uid,
            'company_order_id'  => $info->id,
            'company_order_pid' => $info->pid,
            'pay_type'          => $post['pay_type'],
            'reason'            => ReasonType::ORDER,
            'money'             => $post['money'] ?? 0,
            'image'             => $post['image'] ?? '',
            'remark'            => $post['remark'] ?? '',
            'account_record_id' => $accountId,
        ];
        (new ReceiveLog())->save($payData);
        return $update;
    }

    private function addAccountPaymentRecord(mixed $post, mixed $accountId, mixed $info): void
    {
        if ($post['pay_type'] == PayType::BANK) {
            (new AccountPaymentRecord())->save([
                'no'         => generateOrderNo('SK'),
                'company_id' => $this->companyId,
                'account_id' => $accountId,
                'payee_type' => PaymentPayeeType::SALES,
                'payee_id'   => $this->uid,
                'store_id'   => $info->store_id,
                'amount'     => $post['money'],
                'channel'    => '公司账户款项',
                'pay_type'   => PayType::BANK,
                'remark'     => $post['remark'] ?? '',
                'voucher'    => $post['image'] ?? '',
            ]);
        }
    }

    private function dealYc($newInfo, $post, $update): array
    {
        // 预存要扣减冻结的钱，然后司机提交拍照信息
        $update['pay_amount']   = $newInfo->delivery_amount;
        $update['unsay_amount'] = 0;
        $update['pay_status']   = PayStatus::SETTLED;
        // 修改门店业务员的冻结金额
        $ssInfo = SalesmanStore::where('salesman_id', $newInfo->salesman_id)
            ->where('store_id', $newInfo->store_id)->find();
        $oldBalance = $ssInfo->balance;
        $oldFreeze = $ssInfo->freeze;
        // 记录门店余额变动情况
        // 判断金额大小
        if ($newInfo->yc_money >= $newInfo->delivery_amount) {
            // 签收金额小于已付预存款金额，回退预存款
            $diffMoney = bcsub($newInfo->yc_money, $newInfo->delivery_amount, 2);
            $ssInfo->dec('freeze', $newInfo->yc_money)->inc('balance', $diffMoney)->save();
            $balanceLogData = [
                'company_id' => $this->companyId,
                'salesman_id' => $newInfo->salesman_id,
                'store_id' => $newInfo->store_id,
                'creator_type' => StoreBalanceLog::TYPE_SALESMAN,
                'creator_id' => $this->uid,
                'company_order_id' => $newInfo->id,
                'old_balance' => $oldBalance,
                'new_balance' => bcadd($oldBalance, $diffMoney, 2),
                'old_freeze' => $oldFreeze,
                'new_freeze' => bcsub($oldFreeze, $newInfo->yc_money, 2),
                'remark' => StoreBalanceLog::REMARK_CX,
            ];
        }
        if (isset($balanceLogData)) (new StoreBalanceLog())->save($balanceLogData);
        return $update;
    }

    /**
     * 订单列表
     * @throws DbException
     */
    public function list(): Json
    {
        $get   = $this->request->get();
        $where = [];
        if (!empty($get['order_status']) && $get['order_status'] != 0) {
            $where[] = ['order_status', '=', $get['order_status']];
        }
        if ($this->userInfo['scene_id'] == 2) {
            $where[] = ['salesman_id', '=', $this->uid];
        } else {
            $where[] = ['dealer_id', '=', $this->uid];
        }
        if(!empty($get['is_cx'])){
            $where[] = ['is_cx', '=', $get['is_cx']];
        }
        $list = $this->model->with([
                                           'detail',
                                           'store'  => function ($query)
                                           {
                                               $query->field('id,name,contact,phone');
                                           },
                                           'dealer' => function ($query)
                                           {
                                               $query->field('id,name,contact,phone');
                                           }
                                   ])
                            ->where($where)
                            ->where('pid', '<>', 0)
                            ->where('order_type', OrderType::SALES)
                            ->append(['pay_status_text', 'receive_type_text', 'order_status_text', 'can_cancel'])
                            ->order('id desc')->paginate($get['limit'] ?? 15)->each(function ($item)
                {
                    $item->can_cancel_text = $item->can_cancel == 1 ? '可取消' : '不可取消';
                    if($item->is_cx == 1){
                        $where = [
                            ['payee_type','=', 2],
                            ['payee_id','=',  $item->driver_id],
                        ];
                    }else{
                        $where = [
                            ['payee_type','=', 1],
                            ['payee_id','=',  $item->salesman_id],
                        ];
                    }
                    $item->receive_log = (new ReceiveLog())->where('company_order_id', $item->id)->where($where)->find();
                });
        return $this->success($list);
    }

    /**
     * @NodeAnnotation(title="小程序取消订单")
     * @param Request $request
     * @return Json
     */
    public function cancel(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $this->sceneValidate($post, 'cancel');
        try {
            // 验证订单真实性
            $orderInfo = $this->model->with('detail')->find($post['id']);
            if (!$orderInfo) {
                return $this->error('订单不存在！');
            }
            if ($orderInfo->driver_id != 0 || $orderInfo->pick_status == 2) {
                return $this->error('订单已出库无法取消！');
            }
            if ($orderInfo->order_status != 1) {
                return $this->error('订单状态不符合取消条件，无法取消！');
            }
            $this->model->transaction(function () use ($post, $orderInfo)
            {
                // 取消订单
                $orderInfo->save(['order_status' => OrderStatus::CANCEL]);
                $this->model->where('id',$orderInfo->pid)->save(['order_status' => OrderStatus::CANCEL]);
                // 回退库存
                array_map(function ($vo)use($orderInfo)
                {
                    $specInfo = (new DealerGoodsSpec())->where('id',$vo['dealer_goods_spec_id'])->find();
                    if($orderInfo->is_cx == 1){
                        (new DealerGoods())->where('id', $vo['dealer_goods_id'])->inc('sales_stock', $vo['num']*$specInfo['ratio'])->save();
                    }else{
                        (new CompanyWarehouseGoods())
                            ->where('dealer_goods_id', $vo['dealer_goods_id'])
                            ->inc('stock', $vo['num']*$specInfo['ratio'])->save();
                    }
                }, $orderInfo['detail']->toArray());
            });
        } catch (\Exception $e) {
            return $this->error('取消失败:' . $e->getMessage());
        }
        return $this->success('取消成功');
    }

    public function detail($id): Json
    {
        $row = $this->model->with([
                                          'detail'   => function ($query)
                                          {
                                              $query->with([
                                                                   'goods'      => function ($query)
                                                                   {
                                                                       $query->field('id,name,image')->withTrashed();
                                                                   },
                                                                   'goods_spec' => function ($query)
                                                                   {
                                                                       $query->field('id,name,image,unit')->withTrashed();
                                                                   }
                                                           ]);
                                          },
                                          'store',
                                          'driver'   => function ($query)
                                          {
                                              $query->field('id,name,phone');
                                          },
                                          'salesman' => function ($query)
                                          {
                                              $query->field('id,username,phone,rename');
                                          },
                                  ]);
        $row = $row->append(['pay_status_text', 'receive_type_text', 'order_status_text', 'can_cancel'])->find($id);
        if($row->is_cx == 1){
            $where = [
                ['payee_type','=', 2],
                ['payee_id','=',  $row->driver_id],
            ];
        }else{
            $where = [
                ['payee_type','=', 1],
                ['payee_id','=',  $row->salesman_id],
            ];
        }
        $row->receive_log = (new ReceiveLog())->where('company_order_id', $row->id)->where($where)->find();
        if (!$row) return $this->error('数据不存在！');
        return $this->success($row);
    }

    /**
     * @NodeAnnotation(title="新增回库订单")
     * @param Request $request
     * @return Json
     * @throws BaseException
     */
    public function returnAdd(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        if (empty($post['detail'])) {
            return $this->error('商品信息缺失！');
        }
        if (!$this->dealer_id) {
            return $this->error('业务员无经销商，不可下单！');
        }
        try {
            $this->model->transaction(function () use ($post)
            {
                $downString = '';
                // 处理订单数据
                $detail = array_map(function ($vo) use ($post, &$downString)
                {
                    // 查询商品状态
                    $info = (new DealerGoods())->field('id,name,status')->where('id', $vo['dealer_goods_id'])->find();
                    if (!$info || $info['status'] == 2) {
                        $downString .= '商品【' . $info['name'] . '】';
                    }
                    // 赠送金额为0
                    if (!$vo['true_price']) $vo['true_price'] = $vo['sale_price'];
                    if ($vo['goods_type'] == GoodsType::GIFT) $vo['true_price'] = 0;
                    $vo['total_price'] = $vo['true_price'] * $vo['num'];
                    return $vo;
                }, json_decode($post['detail'], true));
                if ($downString != '') {
                    throw new BaseException(['message' => $downString . '已禁用或不存在，请删除后再下单！']);
                }
                // 订单公共信息
                $commonOrder = [
                    'company_id'    => $this->companyId,
                    'dealer_id'     => $this->dealer_id,
                    'salesman_id'   => $this->uid,
                    'order_status'  => OrderStatus::BEING,
                    'check_status'  => CheckStatus::YES_CHECK,
                    'store_id'      => $post['store_id'],
                    'receive_type'  => $post['receive_type']??0,
                    'remark'        => $post['remark']??'',
                    'order_channel' => OrderChanel::MINI_PROGRAM,
                    'is_cx'         => $post['is_cx'],
                ];
                // 使用 array_filter 筛选出 goods_type 获取销售金额
                $tkAmountArray = array_filter($detail, function ($item)
                {
                    return in_array($item['goods_type'], [GoodsType::RETURN_GOODS]);
                });
                // 主订单信息
                $order                  = $commonOrder;
                $order['order_no']      = generateOrderNo('KD');
                $order['order_amount']  = array_sum(array_column($tkAmountArray, 'total_price'));
                $order['return_amount'] = $order['order_amount'];
                $order['unsay_amount']  = $order['order_amount'];
                // 子订单信息
                $childOrder = [];
                $info       = $commonOrder;
                // 所有类型
                $goodsType = array_column($detail, 'goods_type');
                // 回库单
                if (in_array(GoodsType::RETURN_GOODS, $goodsType) || in_array(GoodsType::CHANGE_GOODS, $goodsType)) {
                    $info['order_no']      = $order['order_no'] . '-' . OrderType::RETURN;
                    $info['order_type']    = OrderType::RETURN;
                    $info['order_amount']  = $order['order_amount'];
                    $info['return_amount'] = $order['return_amount'];
                    $info['unsay_amount']  = $order['unsay_amount'];
                    $childOrder[]          = $info;

                    // 2024.11.14 生成退款单和增加金额
                    $accountModel = new AccountRecord();
                    $accountInfo  = $accountModel->where('company_id', $this->companyId)
                        ->where('payee_type', AccountRecord::SALESMAN)
                        ->where('payee_id', $this->uid)->find();
                    if (!$accountInfo) {
                        $accountData = [
                            'company_id'   => $this->companyId,
                            'payee_type'   => AccountRecord::SALESMAN,
                            'payee_id'     => $this->uid,
                            'return_money' => $order['return_amount'],
                        ];
                        $accountModel->save($accountData);
                        $accountId = $accountModel->getKey();
                    } else {
                        $accountInfo->inc('return_money', $order['return_amount'])->save();
                        $accountId = $accountInfo->id;
                    }
                    $refundData = [
                        'account_record_id' => $accountId,
                        'company_id'        => $this->companyId,
                        'salesman_id'       => $this->uid,
                        'store_id'          => $post['store_id'],
                        'money'             => $order['return_amount'],
                    ];
                }
                // 保存主订单
                $save = $this->model->save($order);
                if ($save) {
                    $childOrder = array_map(function ($vo)
                    {
                        $vo['pid'] = $this->model->id;
                        return $vo;
                    }, $childOrder);
                    $this->model->saveAll($childOrder);
                }
                // 保存退款单
                if (!empty($refundData)) {
                    $companyOrderId = $this->model->where('pid', $this->model->id)
                        ->where('order_type', OrderType::RETURN)->value('id');
                    if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                    $refundData['company_order_pid'] = $this->model->id;
                    $refundData['company_order_id']  = $companyOrderId;
                    (new Refund())->save($refundData);
                }
                // 保存订单详情
                $detail = array_map(function ($vo)use ($post)
                {
                    $vo['company_order_pid'] = $this->model->id;
                    if ($vo['goods_type'] == GoodsType::RETURN_GOODS || $vo['goods_type'] == GoodsType::CHANGE_GOODS) {
                        // 查询回库类型主键
                        $companyOrderId = $this->model->where('pid', $this->model->id)->where('order_type', OrderType::RETURN)->value('id');
                        if (!$companyOrderId) throw new BaseException(['message' => '数据错误']);
                        $vo['company_order_id'] = $companyOrderId;
                    }
                    $vo['real_num'] = $vo['num'];
                    $vo['company_warehouse_id'] = $post['warehouse_id'];
                    unset($vo['id']);
                    return $vo;
                }, $detail);
                (new CompanyOrderDetail())->saveAll($detail);
                // 删除对应购物车的内容
                (new Cart())->where('store_id', $post['store_id'])->where('salesman_id', $this->uid)->where('company_warehouse_id',$post['warehouse_id'])->where('goods_type',3)->delete();
            });
        } catch (\Exception $e) {
            return $this->error('退货失败' . $e->getMessage());
        }
        return $this->success('退货成功');
    }

    public function returnList(): Json
    {
        $get   = $this->request->get();
        $where = [];
//        if (!empty($get['order_status']) && $get['order_status'] != 0) {
//            $where[] = ['order_status', '=', $get['order_status']];
//        }
        if ($this->userInfo['scene_id'] == 2) {
            $where[] = ['salesman_id', '=', $this->uid];
        } else {
            $where[] = ['dealer_id', '=', $this->uid];
        }
        if(!empty($get['is_cx'])){
            $where[] = ['is_cx', '=', $get['is_cx']];
        }
        $list = $this->model->with([
            'detail',
            'store'  => function ($query)
            {
                $query->field('id,name,contact,phone');
            },
            'dealer' => function ($query)
            {
                $query->field('id,name,contact,phone');
            }
        ])
            ->where($where)
            ->where('pid', '<>', 0)
            ->where('order_type', OrderType::RETURN)
            ->append(['pay_status_text', 'receive_type_text', 'order_status_text', 'can_cancel'])
            ->order('id desc')->paginate($get['limit'] ?? 15)->each(function ($item)
            {
                $item->can_cancel_text = $item->can_cancel == 1 ? '可取消' : '不可取消';
            });
        return $this->success($list);
    }

    /**
     * 修改订单
     * @param Request $request
     * @return Json
     * @throws BaseException
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function changeOrder(Request $request): Json
    {
        // 判断参数是否符合
        // 判断订单是否符合
        // 增加商品或者减少商品一定要判断库存或者回退库存
        // 如果增加商品，配送单和物流单要同步展示
        // 如果有调整一定要重新计算订单相关金额
        // 增加修改记录（为消息系统做准备）
        $this->checkPost();
        $post = $request->post();
        $rule = [
            'id' => 'require',
            'detail' => 'require',
        ];
        $this->validate($post, $rule);
        $orderInfo = $this->model->find($post['id']);
        if($orderInfo->is_cx != 1) return $this->error('车销订单不可修改！');
        if($orderInfo->order_type != 1) return $this->error('该订单类型，不符合修改条件！');
        if($orderInfo->out_status == 2) return $this->error('该订单已出库，无法修改');
        try {
            $this->model->transaction(function () use ($post,$orderInfo){
                $detailModel = new CompanyOrderDetail();
                $specModel = new DealerGoodsSpec();
                $goodsModel = new DealerGoods();
                // 遍历商品，如果有id修改，咩有就增加，删除做diff
                $detail = json_decode($post['detail'], true);
                if(!$detail) throw new BaseException(['message' => '提交时请确保至少有一条商品信息！']);
                // 之前的商品
                $oldDetailIds = $detailModel->where('company_order_id', $post['id'])->whereIn('goods_type',[1,2])->column('id');
                // 新的商品
                $newDetailIds = array_column($detail, 'id');
                // $oldDetailIds和$newDetailIds比较，缺的那些就是应该被删除的商品（diff函数，切忌，参数1是基准，是要看，旧的哪些没有了被删除，所以$oldDetailIds要放参数1）
                $deleteIds = array_diff($oldDetailIds, $newDetailIds);
                $detailModel->whereIn('id', $deleteIds)->save(['delete_time' => time()]);
                // 删除的回退库存
                foreach ($deleteIds as $deleteId) {
                    $detailInfo = $detailModel->find($deleteId);
                    // 判断商品是否存在
                    $specInfo = $specModel->withTrashed()->find($detailInfo['dealer_goods_spec_id']);
                    $goodsInfo = $goodsModel->withTrashed()->find($detailInfo['dealer_goods_id']);
                    // 回退库存
                    $goodsInfo->inc('sales_stock',($detailInfo['num'] * $specInfo->ratio))->save();
                }
                foreach ($detail as $item) {
                    if($item['num'] <= 0) throw new BaseException(['message' => '商品数量不允许为负！']);
                    if($item['true_price'] <= 0) throw new BaseException(['message' => '商品价格不允许为负！']);
                    $specInfo = $specModel->find($item['dealer_goods_spec_id']);
                    $goodsInfo = $goodsModel->find($item['dealer_goods_id']);
                    if(isset($item['id'])){
                        // 有id说明修改
                        $detailInfo = $detailModel->find($item['id']);
                        if(!$goodsInfo || !$specInfo) throw new BaseException(['message' => '商品或商品规格已删除，请删除后调整数据']);
                        if($item['dealer_goods_spec_id'] != $detailInfo['dealer_goods_spec_id']) throw new BaseException(['message' => '有数据进行了调换，请删除后，重新添加新数据']);
                        if($detailInfo->num < $item['num']){
                            // 修改后商品变多，增加订单商品，需要扣减库存
                            // 判断库存是否满足
                            $changeNum = ($item['num'] - $detailInfo->num) * $specInfo->ratio;
                            if($goodsInfo->sales_stock < $changeNum) throw new BaseException(['message' => $goodsInfo['name'].'-库存不足，请重新调整数量']);
                            // 减少库存
                            $goodsInfo->dec('sales_stock',$changeNum)->save();
                        }else{
                            // 修改后商品变少，减少订单商品，需要增加库存
                            $changeNum = ($detailInfo->num - $item['num']) * $specInfo->ratio;
                            // 增加库存
                            $goodsInfo->inc('sales_stock',$changeNum)->save();
                        }
                    }else{
                        // 没有id说明增加
                        $detailData = [
                            'company_order_id' => $orderInfo->company_id,
                            'company_order_pid' => $orderInfo->pid,
                            'dealer_goods_id' => $orderInfo->pid,
                            'dealer_goods_spec_id' => $orderInfo->pid,
                            'goods_type' => $item['goods_type'],
                            'sale_price' => $item['sale_price'],
                            'true_price' => $item['true_price'],
                            'num' => $item['num'],
                            'total_price' => bcmul($item['num'], $item['true_price'],2),
                            'driver_money' => bcmul($item['num'], $specInfo['driver_money'],2),
                            'assist_driver_money' => bcmul($item['num'], $specInfo['assist_driver_money'],2),
                            'remark' => $item['remark'],
                        ];
                        $detailModel->save($detailData);
                    }
                }
                // 处理订单，修改各个相关金额，修改订单状态，查看其他单据是否需要修改
                // 重新获取订单详情，统计现在订单内的数据
                $new_total_price = $detailModel->where('company_order_id',$post['id'])->sum('total_price');
                $new_driver_money = $detailModel->where('company_order_id',$post['id'])->sum('driver_money');
                $new_assist_driver_money = $detailModel->where('company_order_id',$post['id'])->sum('assist_driver_money');
                // 修改销售单
                $orderInfo->save([
                    'order_amount' => $new_total_price,
                    'unsay_amount' => $new_total_price,
                    'driver_money' => $new_driver_money,
                    'assist_driver_money' => $new_assist_driver_money
                ]);
                // 修改访销单
                // 查询子订单合计
                $order_order_amount = $this->model->where('pid',$orderInfo->pid)->sum('order_amount');
                $order_unsay_amount = $this->model->where('pid',$orderInfo->pid)->sum('unsay_amount');
                $this->model->where('id',$orderInfo->pid)->save([
                    'order_amount' => $order_order_amount,
                    'unsay_amount' => $order_unsay_amount,
                ]);
                // 增加修改记录
                $logData = [
                    'company_id' => $orderInfo->company_id,
                    'company_order_id' => $orderInfo->id,
                    'company_order_pid' => $orderInfo->pid,
                    'operator_type' => ChangeCompanyOrderLog::OPERATOR_SALESMAN,
                    'operator_id' => $this->uid,
                    'json' => json_encode($post),
                    'remark' => '业务员'.$this->uid.'操作修改订单',
                ];
                (new ChangeCompanyOrderLog())->save($logData);
            });
        }catch (\Exception $e){
            return $this->error('修改失败：'.$e->getMessage());
        }
        return $this->success('修改成功，请及时同步相关人员');
    }
}